<?php
namespace Twoir\Service\ShowKey;

/**
 * 验证码
 *
 * cighsen02 365182575
 * time: 2024.05.06
*/
class Image implements OutputInterface
{
    private static $mime = [
        'jpg'   => 'image/jpeg',
        'jpeg'  => 'image/jpeg',
        'png'   => 'image/png',
        'gif'   => 'image/gif',
        'wbmp'  => 'image/vnd.wap.wbmp'
    ];

    private static $verifyKey = [
    	// 登陆
    	'login'			=> 'checkloginkey',
    	// 注册
    	'reg'			=> 'checkregkey',
    	'info'			=> 'checkinfokey',
    	'spacefb'		=> 'checkspacefbkey',
    	'spacegb'		=> 'checkspacegbkey',
    	'gbook'			=> 'checkgbookkey',
    	'feedback'		=> 'checkfeedbackkey',
    	'getpassword'	=> 'checkgetpasskey',
    	'regsend'		=> 'checkregsendkey',
    	'report' 		=> 'checkreportkey',
    	// 评论
    	'pl'			=> 'checkplkey'
    ];
    // 默认颜色
    private static $defaltRGB = [
    	// 背景色
    	'keybgcolor' 	=> [102, 102, 102],
    	// 文字色
    	'keyfontcolor'	=> [255, 255, 255],
    	// 干扰色
    	'keydistcolor'	=> [71, 71, 71]
    ];
	// 对象
	private $image;

	private $keytog;
	// array 背景色
	private $bgcolor;
	// array 文字色
	private $fontcolor;
	// array 干扰色
	private $distcolor;

    private $imageType;

	public function __construct($imageType = 'jpeg', $width = 47, $height = 20)
	{
		global $public_r;

		if(!extension_loaded('gd')) throw new \Exception('请先安装gd库！' . $key, 9200);

		$width = $width ? (int)$width : static::WIDTH;

		$height = $height ? (int)$height : static::HEIGHT;

		$this->keytog = (int)$public_r['keytog'];
		// 背景色
		$this->bgcolor = isset($public_r['keybgcolor']) && $public_r['keybgcolor'] ? $this->returnRGB($public_r['keybgcolor']) : static::$defaltRGB['keybgcolor'];
		// 文字色
		$this->fontcolor = isset($public_r['keyfontcolor']) && $public_r['keyfontcolor'] ? $this->returnRGB($public_r['keyfontcolor']) : static::$defaltRGB['keyfontcolor'];
		// 干扰色
		$this->distcolor = isset($public_r['keydistcolor']) && $public_r['keydistcolor'] ? $this->returnRGB($public_r['keydistcolor']) : static::$defaltRGB['keydistcolor'];
		// 画布
		$this->image = imagecreate($width, $height);

        $this->imageType = isset($imageType) && array_key_exists($imageType, static::$mime) ? $imageType : 'jpeg';
	}

	/**
	 * 验证码渲染
	 *
	 * @param array $add
	*/
	public function render($add)
	{
		if (empty($add) || !isset($add['v']) || empty($add['v'])) throw new \Exception('参数错误', 9200);

		if (!isset(static::$verifyKey[$add['v']])) throw new \Exception('无效' . $add['v'], 9200);

		$key = strtolower($this->randomCharacters());

		ecmsSetShowKey(static::$verifyKey[$add['v']], $key);

		return $this->toBase64DataURI($key);
	}

	/**
	 * 生成图像
	 *
	 * @param string $key
	 * @return string
	*/
	private function toBase64DataURI($key)
	{
		$bgcolor = imagecolorallocate($this->image, $this->bgcolor[0], $this->bgcolor[1], $this->bgcolor[2]);
		imagefill($this->image, 0, 0, $bgcolor);
		$fontcolor = imagecolorallocate($this->image, $this->fontcolor[0], $this->fontcolor[1], $this->fontcolor[2]);
		imagestring($this->image, 5, 6, 3, $key, $fontcolor);

        // 加入干扰象素
		for($i = 0; $i < 90; $i++) {

			$distcolor = imagecolorallocate($this->image, $this->distcolor[0], $this->distcolor[1], $this->distcolor[2]);
			imagesetpixel($this->image, rand() % 70, rand() % 30, $distcolor);
		}

        $callback = 'image' . ('jpg' === $this->imageType ? 'jpeg' : $this->imageType);

		ob_start();

        call_user_func($callback, $this->image);

        $imageData = ob_get_contents();

        imagedestroy($this->image);

        ob_end_clean();

		return sprintf('data:image/%s;base64,%s', static::$mime[$this->imageType], base64_encode($imageData));
	}

	/**
	 * 生成随机字符
	 *
	 * @param int $length
	 * @return string
	*/
	public function randomCharacters($length = 4)
	{
		//字母
		if(1 === $this->keytog) {

			$low_ascii_bound	= 65;
			$upper_ascii_bound	= 90;
			$notuse				= [91];
		}
		//数字+字母
		elseif(2 === $this->keytog) {

			$low_ascii_bound	= 50;
			$upper_ascii_bound	= 90;
			$notuse				= [58,59,60,61,62,63,64,73,79];
		}
		//数字
		else {

			$low_ascii_bound	= 48;
			$upper_ascii_bound	= 57;
			$notuse				= [58];
		}

		$string = '';
		$i = 0;
		while($i < $length){

			if(PHP_VERSION < '4.2.0') mt_srand((double)microtime() * 1000000);

			mt_srand();
			$randnum = mt_rand($low_ascii_bound, $upper_ascii_bound);
			if(!in_array($randnum, $notuse)){

				$string .= chr($randnum);
				$i++;
			}
		}

		return $string;
	}

	/**
	 * 把16进制转10进制
	 *
	 * @param string $rgb
	 * @return array
	*/
	private function returnRGB($rgb)
	{
		$rgb = str_replace('#', '', ehtmlspecialchars($rgb));

		return [
			base_convert(substr($rgb, 0, 2), 16, 10),
			base_convert(substr($rgb, 2, 2), 16, 10),
			base_convert(substr($rgb, 4, 2), 16, 10)
		];
	}
}
